import re
from django.conf import settings
from django.core.mail import send_mail
from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
from oauth.models import OauthQQUser, OAuthSinaUser
from itsdangerous import TimedJSONWebSignatureSerializer as TJS
from users.models import User


class OauthViewSerializer(serializers.ModelSerializer):
    sms_code = serializers.CharField(min_length=6, max_length=6, write_only=True)
    access_token = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)
    user_id = serializers.IntegerField(read_only=True)
    mobile = serializers.CharField(max_length=11)

    class Meta:
        model = User
        fields = ('mobile', 'username', 'sms_code', 'access_token', 'password',
                  'token', 'user_id')

        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'password': {
                'write_only': True
            }
        }

    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('沙雕手机号格式错了')
        return value

    def validate(self, attrs):
        # 验证access_token
        tjs = TJS(settings.SECRET_KEY, 300)
        try:
            data = tjs.loads(attrs['access_token'])
        except:
            raise serializers.ValidationError('access_token，我觉得不行')

        # 获取openid
        openid = data['openid']
        attrs['openid'] = openid

        # 检查验证码
        conn = get_redis_connection('sms_session')
        a = attrs['mobile']
        rel_sms_code = conn.get('mobile_%s' % attrs['mobile'])
        if not rel_sms_code:
            raise serializers.ValidationError('验证码guoqi')
        if attrs['sms_code'] != rel_sms_code.decode():
            raise serializers.ValidationError('验证码输入错误')

        # 检查是否注册过
        try:
            user = User.objects.get(mobile=attrs['mobile'])
        except:
            return attrs
        else:
            # 判断密码正确
            if not user.check_password(attrs['password']):
                raise serializers.ValidationError('密码错误')
            attrs['user'] = user
            return attrs

    def create(self, validated_data):
        user = validated_data.get('user', None)
        if not user:
            User.objects.create(username=validated_data['mobile'],
                                mobile=validated_data['mobile'],
                                password=validated_data['password'])

        # 绑定
        OauthQQUser.objects.create(user=user, openid=validated_data['openid'])

        # token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)  # 载荷
        token = jwt_encode_handler(payload)  # token

        user.token = token

        return user


class OauthWeiboSerializers(serializers.ModelSerializer):
    # 显示指明模型类中没有的字段
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
    access_token = serializers.CharField(write_only=True)
    token = serializers.CharField(read_only=True)
    user_id = serializers.IntegerField(read_only=True)
    mobile = serializers.CharField(max_length=11)

    class Meta:
        model = User
        fields = ('password', 'mobile', 'username', 'sms_code', 'token', 'access_token', 'user_id')

        extra_kwargs = {
            'username': {
                'read_only': True
            },
            'password': {
                'write_only': True
            },

        }

    # 验证手机号格式
    def validate_mobile(self, value):
        if not re.match(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError('手机号格式不正确')
        return value

    def validate(self, attrs):
        # 验证access_token
        # 解密
        tjs = TJS(settings.SECRET_KEY, 300)
        try:
            data = tjs.loads(attrs['access_token'])
            print(data)
        except:
            raise serializers.ValidationError('无效access_token')
        print(data)

        # 获取access_token
        access_token = data.get('access_token')

        # attrs添加access_token
        attrs['access_token'] = access_token
        print(attrs)
        # 验证短信验证码
        # 1、获取reids中真实短信
        conn = get_redis_connection('sms_session')
        rel_sms_code = conn.get('mobile_%s' % attrs['mobile'])

        # 2、判断短信是否超过有效期
        if not rel_sms_code:
            raise serializers.ValidationError('短信验证码过期')
        # 3、比对用户输入的短信和redis中真实短信

        if attrs['sms_code'] != rel_sms_code.decode():
            raise serializers.ValidationError('短信验证不一致')
            # 判断手机号用户是否注册过
        try:
            user = User.objects.get(mobile=attrs['mobile'])
        except:
            # 未注册过，注册为新用户
            return attrs
        else:
            # 注册过 查询用户进行绑定
            # 判断密码
            if not user.check_password(attrs['password']):
                raise serializers.ValidationError('密码错误')
            attrs['user'] = user
            return attrs



    def create(self, validated_data):
        # 判断用户
        user = validated_data.get('user', None)
        if user is None:
            # 创建用户
            user = User.objects.create_user(username=validated_data['mobile'], password=validated_data['password'],
                              mobile=validated_data['mobile'])
        # 绑定操作
        OAuthSinaUser.objects.create(user=user, access_token=validated_data['access_token'])
        # 生成加密后的token数据
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)  # 生成载荷部分
        token = jwt_encode_handler(payload)  # 生成token

        # user添加token属性
        user.token = token
        user.user_id = user.id

        return user